#include "simulation_engine.h"
#include <QDateTime>
#include <QString>

namespace application {
namespace simulation {

SimulationEngine::SimulationEngine(
    std::shared_ptr<MapApplicationService> mapService,
    std::shared_ptr<kernel::ILogger> logger,
    QObject* parent)
    : QObject(parent)
    , m_logger(logger)
    , m_clock(std::make_unique<SimulationClock>())
    , m_physicsSimulator(std::make_unique<PhysicsSimulator>(mapService, logger))
    , m_timer(new QTimer(this))
    , m_isPlaying(false)
    , m_lastTickTime(0)
{
    m_timer->setInterval(TIMER_INTERVAL_MS);
    connect(m_timer, &QTimer::timeout, this, &SimulationEngine::onTimerTick);
}

void SimulationEngine::init() {
    if (m_logger) {
        m_logger->info("仿真引擎初始化");
    }
}

void SimulationEngine::play() {
    if (m_isPlaying) {
        return;
    }

    m_isPlaying = true;
    m_clock->setPaused(false);
    m_lastTickTime = QDateTime::currentMSecsSinceEpoch();
    m_timer->start();

    if (m_logger) {
        const QString msg = QStringLiteral("仿真开始播放，时间缩放: %1")
                                .arg(m_clock->getTimeScale(), 0, 'f', 2);
        m_logger->info(msg);
    }

    emit simulationStarted();
}

void SimulationEngine::pause() {
    if (!m_isPlaying || m_clock->isPaused()) {
        return;
    }

    m_clock->setPaused(true);

    if (m_logger) {
        const QString msg = QStringLiteral("仿真暂停，当前时间: %1s")
                                .arg(m_clock->getSimulationTime(), 0, 'f', 2);
        m_logger->info(msg);
    }

    emit simulationPaused();
}

void SimulationEngine::resume() {
    if (!m_isPlaying || !m_clock->isPaused()) {
        return;
    }

    m_clock->setPaused(false);
    m_lastTickTime = QDateTime::currentMSecsSinceEpoch();  // 重置时间戳避免跳跃

    if (m_logger) {
        const QString msg = QStringLiteral("仿真恢复，当前时间: %1s")
                                .arg(m_clock->getSimulationTime(), 0, 'f', 2);
        m_logger->info(msg);
    }

    emit simulationResumed();
}

void SimulationEngine::stop() {
    m_isPlaying = false;
    m_timer->stop();
    m_clock->reset();

    if (m_logger) {
        m_logger->info("仿真停止");
    }

    emit simulationStopped();
    emit simulationTimeChanged(0.0);
}

void SimulationEngine::step(double deltaTime) {
    m_clock->step(deltaTime);

    // 更新所有注册的车辆
    double simDeltaTime = deltaTime;
    for (int agvNumber : m_registeredVehicles) {
        m_physicsSimulator->updateVehicle(agvNumber, simDeltaTime);
    }

    double currentTime = m_clock->getSimulationTime();
    emit simulationTimeChanged(currentTime);

    if (m_logger) {
        const QString msg =
            QStringLiteral("仿真步进 %1s，当前时间: %2s")
                .arg(deltaTime, 0, 'f', 3)
                .arg(currentTime, 0, 'f', 2);
        m_logger->debug(msg);
    }
}

void SimulationEngine::setTimeScale(double scale) {
    m_clock->setTimeScale(scale);

    if (m_logger) {
        const QString msg =
            QStringLiteral("时间缩放设置为: %1").arg(scale, 0, 'f', 2);
        m_logger->info(msg);
    }
}

double SimulationEngine::getTimeScale() const {
    return m_clock->getTimeScale();
}

double SimulationEngine::getSimulationTime() const {
    return m_clock->getSimulationTime();
}

bool SimulationEngine::isPaused() const {
    return m_clock->isPaused();
}

void SimulationEngine::registerVehicle(int agvNumber) {
    m_registeredVehicles.insert(agvNumber);

    if (m_logger) {
        m_logger->debug(QStringLiteral("仿真引擎: 注册车辆 AGV%1").arg(agvNumber));
    }
}

void SimulationEngine::unregisterVehicle(int agvNumber) {
    m_registeredVehicles.remove(agvNumber);

    if (m_logger) {
        m_logger->debug(QStringLiteral("仿真引擎: 注销车辆 AGV%1").arg(agvNumber));
    }
}

void SimulationEngine::onTimerTick() {
    qint64 currentTime = QDateTime::currentMSecsSinceEpoch();
    double realDeltaTime = (currentTime - m_lastTickTime) / 1000.0;  // 转换为秒
    m_lastTickTime = currentTime;

    // 更新仿真时钟
    m_clock->tick(realDeltaTime);

    if (!m_clock->isPaused()) {
        // 计算仿真时间增量（考虑时间缩放）
        double simDeltaTime = realDeltaTime * m_clock->getTimeScale();

        // 更新所有注册的车辆
        for (int agvNumber : m_registeredVehicles) {
            m_physicsSimulator->updateVehicle(agvNumber, simDeltaTime);
        }

        emit simulationTimeChanged(m_clock->getSimulationTime());
    }
}

} // namespace simulation
} // namespace application
